const Api = require("./Api");

class ApiGroupAnalyzer {

    /**
     *
     * @param {Api[]} apis
     * @param {{apiId: string, type: string, urlPath: string, name: string, value: string, jsonPath: string, relationships: string[]}[]} variables
     */
    constructor(apis, variables) {
        this.apis = apis;
        /** @type {{apiId: string, type: string, urlPath: string, name: string, value: string, jsonPath: string, relationships: string[]}[]} */
        this.variables = variables;
        /** @type {{name: string, apis: Api[]}[]} */
        this.groups = [];
    }


    /**
     * 分析 API 请求并将其分组。
     * 首先使用同步分组方法对 API 请求进行分组，然后为每个分组命名，
     * 并使用异步分组方法对分组内的 API 进行进一步分组。
     * @returns {{name: string, apis: Api[]|Api[][]}[]} - 一个包含分组信息的数组，每个分组包含名称和 API 请求数组。
     */
    analyze() {
        this.groups = ApiGroupAnalyzer._syncGroup(this.apis);
        this.groups = this.groups.map((group, index) => {
            return {
                name: `步骤${String(index + 1).padStart(3, "0")}`,
                apis: ApiGroupAnalyzer._asyncGroup(group, this.variables)
            }
        });
        return this.groups;
    }

    /**
     * 同步分组方法，根据 API 请求的开始时间和结束时间将 API 请求分组。
     * 当相邻两个请求的开始时间间隔超过 2000 毫秒时，会创建一个新的分组。
     * @param {Api[]} apis - API 请求数组。
     * @returns {Api[][]} - 一个二维数组，每个子数组代表一个分组，包含一组 API 请求。
     */
    static _syncGroup(apis) {
        const groups = [];
        let currentGroupEndTime = -Infinity;
        for (let i = 0; i < apis.length; i++) {
            const api = apis[i];
            if (api.startTime - currentGroupEndTime > 2000) {
                groups.push([apis[i]]);
                currentGroupEndTime = api.endTime;
            } else {
                groups[groups.length - 1].push(api);
                currentGroupEndTime = Math.max(currentGroupEndTime, api.endTime);
            }
        }
        return groups;
    }

    /**
     * 异步分组方法，根据 API 请求的开始时间和结束时间将 API 请求分组。
     * 当相邻两个请求的开始时间间隔小于等于 10 毫秒，并且当前请求的开始时间早于前一个请求的结束时间时，
     * 它们会被分到同一组。否则，会创建一个新的分组。
     * @param {Api[]} apis - API 请求数组。
     * @param {{apiId: string, type: string, urlPath: string, name: string, value: string, jsonPath: string, relationships: string[]}[]} variables
     * @returns {Api[]|Api[][]} - 一个数组，元素可以是单个 API 实例或包含多个 API 实例的数组，每个元素代表一个分组。
     */
    static _asyncGroup(apis, variables) {
        const groups = [];
        /** @type {Api[]} */
        let currentGroup = [];
        for (let i = 0; i < apis.length; i++) {
            if (i === 0 || (apis[i].startTime - apis[i - 1].startTime <= 10 && apis[i].startTime < apis[i - 1].endTime)) {
                const hasDependency = variables && variables
                    .filter(variable => variable.type.includes("RESPONSE") && currentGroup.find(api => api.id === variable.apiId))
                    .find(variable => variable.relationships.find(apiId => apiId === apis[i].id));
                if (hasDependency) {
                    groups.push(currentGroup.length === 1 ? currentGroup[0] : currentGroup);
                    currentGroup = [apis[i]];
                } else {
                    currentGroup.push(apis[i]);
                }

            } else {
                groups.push(currentGroup.length === 1 ? currentGroup[0] : currentGroup);
                currentGroup = [apis[i]];
            }
        }
        if (currentGroup.length > 0) {
            groups.push(currentGroup.length === 1 ? currentGroup[0] : currentGroup);
        }
        return groups;
    }

}

module.exports = ApiGroupAnalyzer;